<template>
  <view :id="$sUid" class="s-dropdown-menu" :class="custom_class" :style="custom_style">
    <view class="s-dropdown-menu__list" :style="menu_style">
      <view
        v-for="(item, index) of itemDataList"
        :key="index"
        class="s-dropdown-menu__item"
        :class="itemClassList[index]"
        :style="itemStyleList[index]"
        @click="onMenuClick(index)"
      >
        <slot name="menu" :scopeParams="scopeParams" :item="item" :index="index">
          <text class="s-dropdown-menu__item-title s-ellipsis">{{ item.title }}</text>
          <view class="s-dropdown-menu__item-arrow"></view>
        </slot>
      </view>
    </view>
    <slot />
  </view>
</template>

<script>
import componentMixin from '../../mixins/componentMixin';
const MenuSet = new Set();

/**
 * s-dropdown-menu 下拉菜单
 * @description 向下弹出的菜单列表
 * @property {String} activeColor 菜单标题和选项的选中态颜色
 * @property {String} duration = [down | up ] 菜单展开方向
 * @property {Number|String} zIndex 菜单栏 z-index 层级
 * @property {Number|String} duration 动画时长，单位毫秒，设置为 0 可以禁用动画
 * @property {Boolean} mask 同popup组件mask属性
 * @property {Boolean} maskClose 点击遮罩是否关闭
 * @property {Number|String} maskOpacity 同popup组件maskOpacity属性
 * @example <s-dropdown-menu></s-dropdown-menu>
 */
export default {
  name: 'SDropdownMenu',
  mixins: [componentMixin],
  props: {
    activeColor: String,
    direction: {
      type: String,
      default: 'down',
    },
    zIndex: {
      type: [String, Number],
      default: 10,
    },
    duration: {
      type: [Number, String],
      default: 300,
    },
    mask: {
      type: Boolean,
      default: true,
    },
    maskClose: {
      type: Boolean,
      default: true,
    },
    maskOpacity: [Number, String],
  },
  data: () => ({
    visible: false,
    list: [],
  }),
  computed: {
    isOpen() {
      return this.list.some(item => item.inVisible);
    },
    menu_style() {
      return this.$mergeStyle({
        zIndex: this.isOpen ? (+this.zIndex + 1) : '',
      });
    },
    arrow_icon() {
      return this.direction === 'down' ? 'arrow-down' : 'arrow-up';
    },
    itemDataList() {
      return this.list.map(item => {
        const option = item.validOptions.find(a => a[item.valueKey] === item.value);
        return {
          title: item.title || option[item.labelKey] || '',
          visible: item.visible,
          disabled: item.disabled,
        };
      });
    },
    itemClassList() {
      return this.list.map(item => {
        return this.$mergeClass(`s-dropdown-menu__item--${this.direction}`, {
          's-dropdown-menu__item--active': item.visible,
          's-dropdown-menu__item--disabled': item.disabled,
        });
      });
    },
    itemStyleList() {
      return this.list.map((item, index) => {
        return this.$mergeStyle({
          color: item.visible ? this.activeColor : '',
        });
      });
    },
  },
  created() {
    const systemInfo = uni.getSystemInfoSync();
    this.windowHeight = systemInfo.windowHeight;
    this.windowTop = systemInfo.windowTop || 0;
    this.windowBottom = systemInfo.windowBottom || 0;
    MenuSet.add(this);
  },
  beforeDestroy() {
    MenuSet.delete(this);
  },
  methods: {
    getRect() {
      return this.$getRect(`#${this.$sUid}`);
    },
    onMenuClick(index) {
      const obj = this.list[index];
      if (obj.disabled) return;
      for (const vm of MenuSet.values()) {
        vm.list.forEach(item => {
          if (item !== obj) {
            item.toggle(false, true);
          }
        });
      }
      obj.toggle();
    },
  },
};
</script>

<style lang="scss" src="./index.scss"></style>
